package samsung.sds.systemMonitor.exceptionMonitor.service.impl;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import samsung.sds.system.common.baseQuery.AbstractBaseService;
import samsung.sds.system.common.baseQuery.BaseMapper;
import samsung.sds.system.utils.CommonTools;
import samsung.sds.systemMonitor.exceptionMonitor.dao.ExceptionMonitorMapper;
import samsung.sds.systemMonitor.exceptionMonitor.model.ExceptionEntity;
import samsung.sds.systemMonitor.exceptionMonitor.service.ExceptionMonitorService;
/**
 *  @author deng1.pan
 *  @createDate 2016-02-03
 *  
 *  异常日志模块的service实现类
 */
@Service
public class ExceptionMonitorServiceImpl extends AbstractBaseService<ExceptionEntity> implements ExceptionMonitorService {
	
	@Autowired
	ExceptionMonitorMapper exceptionMonitorMapper;
	
	@Override
	protected BaseMapper<ExceptionEntity> getMapper() {
		return exceptionMonitorMapper;
	}
	
	public int insertEntity(ExceptionEntity exception){
		return this.getMapper().insertEntity(exception);
	}
	/**
	 * 将捕获到的异常封装成实体
	 * @param e
	 * @param request
	 * @return
	 */
	public ExceptionEntity packageException(Throwable e,HttpServletRequest request){
		
		ExceptionEntity exception = new ExceptionEntity();
		if(getStackInfo(e).indexOf("JasperException")>=0){
			exception.setExpName("JasperException");
		}else{
			exception.setExpName(this.getExpName(e));
		}
		exception.setId(CommonTools.getKeyUUID());
		exception.setRequestURL(request.getRequestURI());
		String createUser = (String) request.getSession().getAttribute(
				"SESSION_USERNAME");
		if(createUser==null){
			createUser = "No User Login";
		}
		exception.setCreateUser(createUser);
		exception.setStackInfo(getStackInfo(e));
		getExceptionClassMehtod(e, exception);
		return exception;
	}
	
	/**
	 * 得到异常发生的类名
	 * @param expMessage
	 * @return
	 */
	private  String  getExpName(Throwable e ){
		String  str;
		if(e.getCause()==null){
			str = e.getClass().getName();
		}else{
			str = e.getCause().getClass().getName();
		}
		return  str.substring(str.lastIndexOf(".")+1);
	}
	
	/**
	 * 得到异常的栈信息
	 * @param e
	 * @return
	 */
	private  String  getStackInfo(Throwable e){
		 String stackInfo="";
		 ByteArrayOutputStream buf = null;
		try {
			 buf = new ByteArrayOutputStream();
			 e.printStackTrace(new PrintWriter(buf, true));
			 stackInfo = buf.toString();
			 
		}finally{
			if(buf!=null){
				try {
					buf.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		}
		return  stackInfo;
	}
	
	/**
	 * 解析异常打印结果，得到异常发生的类名和方法名
	 * @param e
	 */
	private void getExceptionClassMehtod(Throwable e, ExceptionEntity exceptionEntity) {
		StringWriter sw = new StringWriter();  
		e.printStackTrace(new PrintWriter(sw, true));  
		String str = sw.toString();  
		String[] exceptionStack = str.split("\tat ");
		int causeLine = 0;
		for (int i = 0; i < exceptionStack.length; i++ ) {
			String stack = exceptionStack[i];
			if( stack.indexOf("Caused by: ") > -1){
				causeLine = i + 1;
				break;
			}
		}
		//解析异常信息，在Cause  by 之后的信息中解析到异常发生的类和方法
		for (int  j = causeLine; j<exceptionStack.length ;j++){
			String  stack=exceptionStack[j];
			if(stack.indexOf("samsung.sds.")>=0){
				causeLine=j;
				break;
			}
		}
		String causeClass;
		if( causeLine > 0 ){
			causeClass = exceptionStack[causeLine];
		} else {
			causeClass = exceptionStack[ 1 ];
		}
		
		int start = causeClass.indexOf("(");
		int colon = causeClass.indexOf(":");
		
		String classMethod = causeClass.substring(0, start);
		String className = causeClass.substring( start+1, colon);
		String method = classMethod.substring( classMethod.lastIndexOf(".") + 1 );
		exceptionEntity.setExpClass( className.replace(".java", ""));
		exceptionEntity.setExpMethod( method );
	}
	
	/**
	 * 获取expName列表
	 */
	@Override
	public List<String> getQueryParam() {
		
		return exceptionMonitorMapper.selectSYS_MONITOR_EXCEPTION01();
	}

}
